var fs = require('fs');

function apply(o, c, defaults) {
    if (defaults) {
        apply(o, defaults);
    }
    if (o && c && typeof c === 'object') {
        for (var p in c) {
            o[p] = c[p];
        }
    }
    return o;
};

var messages = {
	100: 'Continue',
	101: 'Switching Protocols',
	103: 'Checkpoint',
	200: 'OK',
	201: 'Created',
	202: 'Accepted',
	203: 'Non-Authoritative Information',
	204: 'No Content',
	205: 'Reset Content',
	206: 'Partial Content',
	300: 'Multiple Choices',
	301: 'Moved Permanently',
	302: 'Found',
	303: 'See Other',
	304: 'Not Modified',
	306: 'Switch Proxy',
	307: 'Temporary Redirect',
	308: 'Resume Incomplete',
	400: 'Bad Request',
	401: 'Unauthorized',
	402: 'Payment Required',
	403: 'Forbidden',
	404: 'Not Found',
	405: 'Method Not Allowed',
	406: 'Not Acceptable',
	407: 'Proxy Authentication Required',
	408: 'Request Timeout',
	409: 'Conflict',
	410: 'Gone',
	411: 'Length Required',
	412: 'Precondition Failed',
	413: 'Request Entity Too Large',
	414: 'Request-URI Too Long',
	415: 'Unsupported Media Type',
	416: 'Requested Range Not Satisfiable',
	417: 'Expectation Failed',
	500: 'Internal Server Error',
	501: 'Not Implemented',
	502: 'Bad Gateway',
	503: 'Service Unavailable',
	504: 'Gateway Timeout',
	505: 'HTTP Version Not Supported',
	511: 'Network Authentication Required'
};


function Module(cfg) {
    this.cfg = cfg || { path: '', request: null };
    apply(this, cfg);
    this.readylistener = function() {
    };
};

apply(Module.prototype, {
	failureListener: function(code, message, append) {
		code = code || 500;
		message = message || messages[code];
		if (append)
		{
			message = messages[code] + ': ' + message;
		}
		this._response.writeHead(code);
		this._response.end(message);
	},
    onReady: function(listener) {
		if (typeof listener === 'function') {
			this.readylistener = listener;
		}
    },
	getContext: function() {
		return {
			db: this.db,
			config: this.cfg,
			instance: this,
			listeners: {
				ready: this.readylistener,
				failure: this.failureListener.bind(this)
			}
		};
	},
    execute: function() {
		var parts = this.path.split('/');
		var methodname = parts[parts.length - 1];
		var s = methodname.length;
        var path = (this.path.substr(0, (this.path.length - (s + 1))));
        var filename = './modules' + path + '.js';

		fs.exists('./tPAXX/' + filename, function(exists) {
			if (exists) {
				var module = require(filename);
				var method = module[methodname];

				if (typeof method !== 'function') {
					this.failureListener(404, 'method', true);
					return;
				}

				method(this.request, this.readylistener, this.failureListener.bind(this), this.getContext());
			} else {
				this.failureListener(404, 'module', true);
				return;
			}
		}.bind(this));
    }
});
module.exports = Module;